<template>
  <div class="img-contrast-viewer">
    <div class="paln-box">
      <div
        class="movableItem"
        :style="{ width: width, height: height }"
        @mousewheel="rollImg($event,0)"
        @DOMMouseScroll="rollImg($event,0)"
        @mousedown="drag($event, 1)"
        ref="bigImage0"
        ondragstart="return false"
      >
        <!-- 图片不可选中 或不可拖拽到新标签打开-->
        <img
          :src="imgUrl1"
          oncontextmenu="return false;"
          onselectstart="return false;"
          draggable="false"
          alt
        />
      </div>
    </div>
    <div class="paln-box">
      <canvas
        v-if="isEdit"
        :style="{cursor: type?'copy':'crosshair'}"
        class="movableItem"
        id="myCanvas"
        ref="myCanvas"
        :width="width"
        :height="height"
        @mousedown="mousedown"
        @mouseup="mouseup"
        @mousemove="mousemove"
      >
      </canvas>
      <img crossOrigin="anonymous" v-if="isEdit" :src="imgUrl2" :style="{ width: width, height: height,display:'none'}" class="movableItemimg">
      <div
        v-else
        class="movableItem"
        :style="{ width: width, height: height }"
        @mousewheel="rollImg($event,1)"
        @DOMMouseScroll="rollImg($event,1)"
        @mousedown="drag($event, 1)"
        ref="bigImage1"
        ondragstart="return false"
      >
        <img
          :src="imgUrl2"
          oncontextmenu="return false;"
          onselectstart="return false;"
          draggable="false"
          alt
        />
      </div>
      <div class="button-box" v-if="isEdit">
        <el-button size="mini" type="success" plain @click="type=!type">{{type?'矩形框':'画笔'}}</el-button>
        <el-button size="mini" type="primary" plain @click="totalRect=[];clear()">清除画布</el-button>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name:'ImgContrastViewer',
  props: {
    imgUrl1: {
      default: ''
    },
    imgUrl2: {
      default: ''
    },
    isEdit: {
      default: false
    },
  },

  data() {
    return {
      type:true,
      // 画布
      flag: false,
      rectWidth: 0,  //矩形框的宽
      rectHeight: 0, //矩形框的高
      totalRect: [],  //画的所有的矩形坐标长度数据存储在数组中
      downX: 0,  //鼠标点击图片落下时的位置（X）
      downY: 0,   //鼠标点击图片落下时的位置（Y）
      ctx: "",   //dom节点
      canvas: null,
      rectTag: false,
      delIndex: null,  //删除时选中的矩形框的index
      atime: null,
      // 图片
      ms: 20, //函数节流 ms 时间触发一次
	    lastClick: Date.now() - 20,
      // 定时器
      timer: "",
      // 图片加载失败
      imgOnerror: false,
      imgIndex: 0,
      isChange: true,
      // 图片显示默认大小
      width: "1000px",
      height: "600px",
      // 可缩小倍数,为空则可无限缩小
      minification: 3,  
      // 可放大倍数 为空则可无限放大
      magnification: "",
      bigMaxWidth: 1600,
      bigMaxHeight: 800,
      isMove:false,
      offsetX: 0,
      offsetY: 0
    };
  },
  methods: {
    canvasMousedown(e) {
      this.offsetX = e.offsetX
      this.offsetY = e.offsetY
      this.ctx.beginPath()
      this.ctx.strokeStyle = "red";
      this.ctx.lineWidth = 1;
      this.ctx.lineCap = 'round'
      this.ctx.lineJoin = "round";
      this.ctx.moveTo(this.offsetX, this.offsetY)
      this.isMove = true
    },
    canvasMousemove(e) {
      if (this.isMove) {
        console.log('鼠标按下', e.offsetX, 'offsetY', e.offsetY)
        this.offsetX = e.offsetX
        this.offsetY = e.offsetY
        // 设置绘制下一个点
        this.ctx.lineTo(this.offsetX, this.offsetY)
        this.ctx.stroke()
        this.totalRect.push({
          offsetX: this.offsetX,
          offsetY: this.offsetY
        });
      }
    },
    canvasMouseup() {
      console.log('鼠标抬起')
      this.isMove = false
    },
    // 放下鼠标
    mousedown(e) {
      console.log("鼠标落下");
      if(this.type) return this.canvasMousedown(e)
      this.atime = new Date().getTime();
      this.flag = true;
      this.downX = e.offsetX; // 鼠标落下时的X
      this.downY = e.offsetY; // 鼠标落下时的Y
      this.mousemove(e);
    },
    // 移动鼠标
    mousemove(e) {
      if(this.type) return this.canvasMousemove(e)
      if (this.flag) {
        //判断如果重右下往左上画，这种画法直接return
        if(this.downX - e.offsetX > 0 || this.downY - e.offsetY > 0){
          console.log("重右下往左上画");
          return
        }else{
          console.log("重左上往右下画");
          //如果重左上往右下画，计算出鼠标移动的距离，也就是矩形框的宽和高
          this.rectWidth = Math.abs(this.downX - e.offsetX)
          this.rectHeight = Math.abs(this.downY - e.offsetY)
          console.log("this.rectWidth", this.rectWidth);
          console.log("this.rectHeight", this.rectHeight);
          //判断这个宽高的长度，如果小于10，直接return，因为鼠标移动距离过于短
          //防止点击页面时,会画成一个点，没有意义
          if (this.rectWidth < 10 || this.rectHeight < 10) {
            console.log("只是点击");
            this.rectWidth = 0;
            this.rectHeight = 0;
            return;
          }
          this.clear();   //清空画布
          this.redrawAll();
          this.drawRect(
              this.downX,
              this.downY,
              this.rectWidth,
              this.rectHeight
          );
        }
      }
    },
    // 抬起鼠标
    mouseup(e) {
      if(this.type) return this.canvasMouseup(e)
      // console.log("鼠标抬起");
      this.flag = false;
      let a = new Date().getTime();
      if (a - this.atime > 150) {
        this.rectTag = false;
      } else {
        this.rectTag = true;
      }
      if (this.rectWidth || this.rectHeight) {
        //将画出的数据保存在totalRect中
        this.totalRect.push({
          beforex: this.downX,
          beforey: this.downY,
          rectW: this.rectWidth,
          rectH: this.rectHeight,
        });
      }
    },
    redrawAll(scale) {
      scale = scale || 1
      //    console.log("先画之前画过的图，保证画多个的时候看起来像前一个不消失");
      if (this.totalRect.length > 0) {
        this.totalRect.forEach((e,index) => {
          //    console.log("eeeeeeeeeeeeeeeee",e);
          if(e.beforex){
            e.beforex = e.beforex * scale
            e.beforey = e.beforey * scale
            e.rectW = e.rectW * scale
            e.rectH = e.rectH * scale
            this.drawRect(e.beforex, e.beforey, e.rectW, e.rectH);
          }else{
            e.offsetX = e.offsetX * scale
            e.offsetY = e.offsetY * scale
            this.ctx.lineTo(e.offsetX, e.offsetY)
            this.ctx.stroke()
          }
        });
      }
    },
    //清除画布
    clear() {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      this.ctx.drawImage(document.querySelector('.movableItemimg'), 0, 0, this.canvas.width, this.canvas.height);
      this.ctx.strokeStyle = "red";
      this.ctx.lineWidth = 1;
      this.ctx.lineCap = 'round'
      this.ctx.lineJoin = "round";
    },
    drawRect(x, y, lineW, lineY) {
      //   开始绘制;
      this.ctx.beginPath();
      // strokeRect参数：（左上角x坐标，y:左上角y坐标，绘画矩形的宽度，绘画矩形的高度）
      this.ctx.strokeRect(x, y, lineW, lineY);
      //   console.log("66666666666666");
    },
    //点击画布
    findRect(e) {
      if (this.rectTag) {
        console.log("eeeeeeeeeee", e);
        console.log("this.totalRect", this.totalRect);
        //当点击画布的时候，计算有没有点再矩形框内、哪个矩形框内
        this.totalRect.map((item, index) => {
          if (
              e.offsetX - item.beforex > item.rectW ||
              e.offsetX < item.beforex ||
              e.offsetY - item.beforey > item.rectH ||
              e.offsetY < item.beforey
          ) {
            return;
          } else {
            //找到之后，设置下标
            this.delIndex = index;
          }
        });
      }
    },
    //点击删除按钮
    del() {
      if(this.totalRect.length>1){
        //删除
        if(this.totalRect[this.totalRect.length-1].beforex){
          this.ctx.clearRect(
            this.totalRect[this.totalRect.length-1].beforex - 2,
            this.totalRect[this.totalRect.length-1].beforey - 2,
            this.totalRect[this.totalRect.length-1].rectW + 4,
            this.totalRect[this.totalRect.length-1].rectH + 4
          );
        }
        //删掉totalRect的数据，真正的项目中需要调用后台接口，删掉数据库中存储的数据
        this.totalRect.splice(this.totalRect.length-1, 1);
        //删掉之后，再画一次，刷新页面
        this.redrawAll();
      }
    },
    // 获取图片大小
    // ,objWidth,objHeight
    getImgInfo(
      imgUrl,
      MaxWidth,
      MaxHeight,
      StrWidth,
      StrHeight,
      Array = false,
      arr,
      num = 0
    ) {
      // console.log("objWidthName", this[StrWidth], this[StrHeight]);
      var img = new Image();

      img.src = imgUrl;
      // const vm = this;
      let _this = this;
      img.onerror = () => {
        _this.imgOnerror = true;
        _this.imgIndex =
          _this.arrIcon.length - 1 < 0 ? 0 : _this.arrIcon.length - 1;
        this.timer = setTimeout(() => {
          if (num <= 5) {
            _this.getImgInfo(
              imgUrl,
              MaxWidth,
              MaxHeight,
              StrWidth,
              StrHeight,
              Array,
              arr,
              num + 1
            );
          }
          clearInterval(this.timer);
        }, 2000);
      };
      img.onload = function (e) {
        //  显示时 初始 最大宽度
        let maxWidth = MaxWidth;
        //  显示时 初始 最大高度
        let maxHeight = MaxHeight;
        if (
          e.path[0].naturalWidth <= maxWidth &&
          e.path[0].naturalHeight <= maxHeight
        ) {
          _this[StrWidth] = e.path[0].naturalWidth + "px";
          _this[StrHeight] = e.path[0].naturalHeight + "px";
        } else {
          _this[StrWidth] = e.path[0].naturalWidth + "px";
          _this[StrHeight] = e.path[0].naturalHeight + "px";
          if (
            e.path[0].naturalWidth > maxWidth &&
            e.path[0].naturalHeight <= maxHeight
          ) {
            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
            _this[StrWidth] = "1600px";
            _this[StrHeight] = maxWidth / ratio + "px";
          } else if (
            e.path[0].naturalWidth <= maxWidth &&
            e.path[0].naturalHeight > maxHeight
          ) {
            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
            _this[StrWidth] = maxHeight * ratio + "px";
            _this[StrHeight] = "800px";
          } else if (
            e.path[0].naturalWidth > maxWidth &&
            e.path[0].naturalHeight > maxHeight
          ) {
            let ratio = e.path[0].naturalWidth / e.path[0].naturalHeight;
            let w = maxWidth;
            let h = w / ratio;
            if (h > maxHeight) {
              let ratio2 = w / h;
              h = maxHeight;
              w = h * ratio2;
            }
            _this[StrWidth] = w + "px";
            _this[StrHeight] = h + "px";
          }
        }
        if (Array) {
          _this[arr].push({
            iconWidth: _this[StrWidth],
            iconHeight: _this[StrHeight],
          });
          console.log(
            "tow#################################arrIcon",
            _this[arr].length
          );
        }
        // _this[StrWidth] = `${e.path[0].naturalWidth}px`;
        // _this[StrHeight] = `${e.path[0].naturalHeight}px`;
        // vm.$set(vm.imgInfo, "width", img.width);
        // vm.$set(vm.imgInfo, "height", img.height);
        // console.log("打印图片信息", imgUrl, _this[StrWidth], _this[StrHeight]); // 打印图片信息

        // console.log("打印图片信息", e.path[0].naturalHeight); // 打印图片信息
        // console.log("打印图片信息", e); // 打印图片信息
        // console.log("打印图片信息this.width", _this[StrWidth]); // 打印图片信息
        // console.log("打印图片信息this.height", _this[StrHeight]); // 打印图片信息
      };
    },
    // 缩放
    rollImg(ev,index) {
      // var oImg = document.getElementsByClassName("movableItem")[0];
      var oImg = this.$refs['bigImage'+index];
      var _this = this;
      function fnWheel(obj, fncc) {
        obj.onmousewheel = fn;
        if (obj.addEventListener) {
          obj.addEventListener("DOMMouseScroll", fn, false);
        }
        function fn(ev) {
          // 函数节流 ms 时间触发一次 解决火狐 ie 卡顿问题
          if (Date.now() - _this.lastClick >= _this.ms) {
            _this.lastClick = Date.now();
            var oEvent = ev || window.event;
            var down = true;
            console.log("oEvent", oEvent);
            if (oEvent.detail) {
              console.log("oEvent.detail", oEvent.detail);
              down = oEvent.detail > 0;
            } else {
              console.log("oEvent.wheelDelta", oEvent.wheelDelta);
              down = oEvent.wheelDelta < 0;
            }
            if (fncc) {
              fncc.call(this, down, oEvent);
            }
            if (oEvent.preventDefault) {
              oEvent.preventDefault();
            }
            return false;
          }
        }
      }
      fnWheel(oImg, function (down, oEvent) {
        let movableItem = document.querySelectorAll('.movableItem')
        var oldWidth = movableItem[index].offsetWidth;
        var oldHeight = this.offsetHeight;
        var oldLeft = this.offsetLeft;
        var oldTop = this.offsetTop;
        var parent = oEvent.path[2];
        // 获取父元素距离页面可视区域的位置
        var parentLeft = parent.getBoundingClientRect().left;
        var parentTop = parent.getBoundingClientRect().top;
        // 比例 = （点击位置距离可视窗口位置 - 父元素距离可视窗口位置 - 相对定位的left）/ 本身宽度
        var scaleX = (oEvent.clientX - parentLeft - oldLeft) / oldWidth; //比例
        var scaleY = (oEvent.clientY - parentTop - oldTop) / oldHeight;

        let nowWidth = this.style.width.split("p")[0];
        let initWidth = _this.width.split("p")[0];
        let initHeight = _this.height.split("p")[0];

        let miniFlag = true;
        let magniFlag = true;
        if (_this.minification) {
          // 限制缩小范围
          if (nowWidth <= parseInt(initWidth / _this.minification)) {
            miniFlag = false;
            console.log("限制缩小范围");
            console.log(
              "限制缩小范围",
              nowWidth,
              parseInt(initWidth / _this.minification)
            );
            this.style.width = parseInt(initWidth / _this.minification) + "px";
            this.style.height =
              parseInt(initHeight / _this.minification) + "px";
          }
          if (_this.magnification) {
            // 限制放大范围
            if (nowWidth >= parseInt(initWidth * _this.magnification)) {
              magniFlag = false;
              console.log("限制放大范围");
              this.style.width =
                parseInt(initWidth * _this.magnification) + "px";
              this.style.height =
                parseInt(initHeight * _this.magnification) + "px";
            }
          }
        }
        let scale = 1
        if (down && miniFlag) {
          console.log("缩小");
          movableItem[0].style.width = parseInt(oldWidth * 0.9) + "px";
          movableItem[0].style.height = parseInt(oldHeight * 0.9) + "px";
          if(_this.isEdit){
            _this.width = parseInt(oldWidth * 0.9) + "px";
            _this.height = parseInt(oldHeight * 0.9) + "px";
            scale = 0.9
          }else{
            movableItem[1].style.width = parseInt(oldWidth * 0.9) + "px";
            movableItem[1].style.height = parseInt(oldHeight * 0.9) + "px";
          }
        } else if (!down && magniFlag) {
          console.log("放大");
          movableItem[0].style.width = parseInt(oldWidth * 1.1) + "px";
          movableItem[0].style.height = parseInt(oldHeight * 1.1) + "px";
          if(_this.isEdit){
            _this.width = parseInt(oldWidth * 1.1) + "px";
            _this.height = parseInt(oldHeight * 1.1) + "px";
            scale = 1.1
          }else{
            movableItem[1].style.width = parseInt(oldWidth * 1.1) + "px";
            movableItem[1].style.height = parseInt(oldHeight * 1.1) + "px";
          }
        }
        var newWidth = this.offsetWidth;
        var newHeight = this.offsetHeight;

        // 新的相对位置left = 原先的相对位置left - 比例 *（本身新的宽度-旧的宽度）
        movableItem[0].style.left = Math.round(oldLeft - scaleX * (newWidth - oldWidth)) + "px";
        movableItem[0].style.top = Math.round(oldTop - scaleY * (newHeight - oldHeight)) + "px";
        movableItem[1].style.left = Math.round(oldLeft - scaleX * (newWidth - oldWidth)) + "px";
        movableItem[1].style.top = Math.round(oldTop - scaleY * (newHeight - oldHeight)) + "px";
        if(_this.isEdit){
          setTimeout(()=>{
            _this.clear();   //清空画布
            _this.redrawAll(scale);
          })
        }
      });
    },
    //拖拽
    drag(ev) {
      // var ie = document.all;
      var nn6 = document.getElementById && !document.all;
      var isdrag = false;
      var y, x;
      var nTY, nTX;
      var oDragObj;
      function moveMouse(e) {
        if (isdrag) {
          let movableItem = document.querySelectorAll('.movableItem')
          movableItem[0].style.top =
            (nn6 ? nTY + e.clientY - y : nTY + event.clientY - y) + "px";
          movableItem[0].style.left =
            (nn6 ? nTX + e.clientX - x : nTX + event.clientX - x) + "px";
          movableItem[1].style.top =
            (nn6 ? nTY + e.clientY - y : nTY + event.clientY - y) + "px";
          movableItem[1].style.left =
            (nn6 ? nTX + e.clientX - x : nTX + event.clientX - x) + "px";
          // console.log("oDragObj.style.top2", oDragObj.style.top);
          // console.log(`nTY+e.clientY-y=${nTY}+${e.clientY}-${y}`);
          // console.log(`nTY+e.clientY-y=${nTY + e.clientY - y}`);

          return false;
        }
      }
      function initDrag(e) {
        if (!e.path) {
          e.path = _this.eventPath(e);
        }
        // console.log("点击图片initDrag");
        var oDragHandle = nn6 ? e.target : event.srcElement;
        var topElement = "HTML";
        while (
          oDragHandle.tagName != topElement &&
          oDragHandle.className != "movableItem"
        ) {
          oDragHandle = nn6
            ? oDragHandle.parentNode
            : oDragHandle.parentElement;
        }
        if (oDragHandle.className == "movableItem") {
          isdrag = true;
          oDragObj = oDragHandle;
          // 父元素宽高
          let width = e.path[2].offsetWidth;
          let height = e.path[2].offsetHeight;
          // console.log(width, height);
          // console.log(oDragObj.style);
          // 这里判断第一次获取不到style 样式 默认为 居中50%
          if (oDragObj.style.top == "") {
            // console.log(
            //   '进入了oDragObj.style.top.indexOf("%")',
            //   oDragObj.style.top
            // );
            nTY = parseInt((50 * height) / 100 + 0);
            nTX = parseInt((50 * width) / 100 + 0);
          } else {
            nTY = parseInt(oDragObj.style.top + 0);
            nTX = parseInt(oDragObj.style.left + 0);
          }
          y = nn6 ? e.clientY : event.clientY;
          x = nn6 ? e.clientX : event.clientX;
          //oDragObj.style.cursor = "move";
          document.onmousemove = moveMouse;
          return false;
        }
      }
      document.onmousemove = initDrag;
      // document.onmouseup = new Function("isdrag=false");
      document.onmouseup = function (e) {
        isdrag = false;
        document.onmousemove = null;
        document.onmouseup = null;
        var oDragHandle = nn6 ? e.target : event.srcElement;
        var topElement = "HTML";
        while (
          oDragHandle.tagName != topElement &&
          oDragHandle.className != "movableItem"
        ) {
          oDragHandle = nn6
            ? oDragHandle.parentNode
            : oDragHandle.parentElement;
        }
        if (oDragHandle.className == "movableItem") {
          oDragObj = oDragHandle;
          //oDragObj.style.cursor = "Default";
        }
      };
      ev = event || window.event;
      // 取消事件冒泡行为
      // window.event ? (window.event.cancelBubble = true) : ev.stopPropagation();
    },
    // FireFox ie和Safari兼容event.path
   eventPath(evt) {
     const path = (evt.composedPath && evt.composedPath()) || evt.path,
       target = evt.target;

     if (path != null) {
       return path.indexOf(window) < 0 ? path.concat(window) : path;
     }

     if (target === window) {
       return [window];
     }

     function getParents(node, memo) {
       memo = memo || [];
       const parentNode = node.parentNode;

       if (!parentNode) {
         return memo;
       } else {
         return getParents(parentNode, memo.concat(parentNode));
       }
     }
     return [target].concat(getParents(target), window);
   },
   getCanvasUrl(){
    const viewPicUrl = this.canvas.toDataURL('image/png')
    return this.base64ToBlob(viewPicUrl)
   },
   // 将canvas的base64转为文件流
    base64ToBlob(urlData, type) {
      const arr = urlData.split(',')
      let mime, bytes
      if (arr && arr.length === 2) {
        mime = arr[0].match(/:(.*?);/)[1] || type
        // 去掉url的头，并转化为byte
        bytes = window.atob(arr[1])
      } else {
        mime = type
        // 去掉url的头，并转化为byte
        bytes = window.atob(arr[0])
      }
      // 处理异常,将ascii码小于0的转换为大于0
      const ab = new ArrayBuffer(bytes.length)
      // 生成视图（直接针对内存）：8位无符号整数，长度1个字节
      const ia = new Uint8Array(ab)
      for (let i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i)
      }
      return new Blob([ab], {
        type: mime
      })
    }
  },
  destroyed() {
    clearInterval(this.timer);
  },
  mounted() {
    let that = this
    if(this.isEdit){
      this.canvas = this.$refs.myCanvas;
      this.ctx = this.canvas.getContext("2d");
      document.querySelector('.movableItemimg').onload = function(){
        setTimeout(() => {
          that.ctx.drawImage(document.querySelector('.movableItemimg'), 0, 0, that.canvas.width, that.canvas.height);
        },300);
      }
    }
  },
  created() {
    this.getImgInfo(
      this.imgUrl1,
      this.bigMaxWidth,
      this.bigMaxHeight,
      "width",
      "height"
    );
    // //禁止鼠标右键
    // document.oncontextmenu = function() {
    //   return false;
    // };
  },
};
</script>
<style lang="scss">
.contrast-preview-popover {
  background-color: #d3edf7dd;
  padding: 12px;
  .popper__arrow::after {
    border-bottom-color: #d3edf7dd !important;
  }
  .describe {
    p {
      padding-bottom: 5px;
      &:last-child {
        padding-bottom: 0px;
      }
    }
    .describe-top {
      // color: sandybrown;
      // color: red;
      color: rgb(21, 110, 110);
    }
    .describe-center {
      color: rgb(79, 21, 206);
    }
    .describe-bottom {
      color: rgb(30, 31, 29);
    }
  }
}
</style>
<style lang="scss" scoped>

.img-contrast-viewer {
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.2);
  display: flex;
  .paln-box {
    width: 50%;
    height: 100%;
    position: relative;
    overflow: hidden;
    &:last-child{
      border-left: 1px solid #eee;
    }
    .movableItem {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      cursor: move;
      img {
        z-index: 1;
        width: 100%;
        height: 100%;
      }
    }
    .shuaxin {
      position: absolute;
      z-index: 2;
      font-size: 40px;
      top: 20px;
      left: 20px;
      cursor: pointer;
      &:hover {
        color: yellowgreen;
      }
    }
    .button-box{
      z-index: 2;
      position: absolute;
      bottom: 10px;
      right: 10px;
    }
  }
}
</style>